# Crime Data from 2010 to Present
# From https://data.lacity.org/A-Safe-City/Crime-Data-from-2010-to-Present/y8tr-7khq/data
#### Heatmap Attempt ####
crime <- read.csv("/Users/charliecarter/Downloads/Crime_Data_from_2010_to_Present.csv",
stringsAsFactors = F)
## Parallel Computing To Derive Latitude and Longitude Quickly ####
library(parallel)
no_cores <- detectCores() - 1
cl <- makeCluster(no_cores)
## get lat
crime$lat <- parLapply(cl, X = crime$Location, fun = function(x) {
as.numeric(
unlist(
strsplit(substr(x, 2, nchar(x) - 1),
split= ", ")[[1]][1]
)
)
})
## get lon
crime$lon <- parLapply(cl, X = crime$Location, fun = function(x) {
as.numeric(
unlist(
strsplit(substr(x, 2, nchar(x) - 1),
split= ", ")[[1]][2]
)
)
})
stopCluster(cl)
crime$lat <- unlist(crime$lat)
crime$lon <- unlist(crime$lon)
#############
## Filter out outlier longitude points
crime <- crime %>%
filter(crime$lon != 0)
## get contour lines that show regions by density
density.poly <- contourLines(
kde2d(crime$lon, crime$lat,
lims = c(
expand_range(range(crime$lon), add = 0.5),
expand_range(range(crime$lat), add = 0.5)
))
)
## create column that subsequent loop will modify
crime$density <- 0
## from highest to lowest density levels (which is default)
## get polygons, assign density val to points within them
for (i in 1:length(density.poly)) {
hold.data <- point.in.polygon(crime$lon, crime$lat,
density.poly[[i]]$x, density.poly[[i]]$y)
crime$density[which(hold.data==1)] <- density.poly[[i]]$level
}
## create year column for animation iteration
crime <- crime %>%
mutate(Date.Occurred = as.Date(Date.Occurred, format = "%m/%d/%Y")) %>%
mutate(year = format(Date.Occurred, "%Y")) %>%
mutate(year = as.integer(year))
## Get Google Map Object from API
ggmap::register_google(key = "AIzaSyBgYVpL1in38KcEnznCFwmRKz2d1VJKSe4")
ggmap_show_api_key()
la.map <- ggmap(get_googlemap("Los Angeles, California"))
#### point with color test ####
crime.density <- la.map +
geom_point(crime, mapping = aes(x = lon, y = lat,
alpha = 0.01,
color = density,
frame = year), size = 0.005, shape = ".") +
scale_color_gradient2(low = "white",
mid = "lightblue",
high = "blue",
midpoint = mean(crime$density, na.rm = T)) +
theme(
legend.position='none'
)
animation::ani.options(interval = 2)
crime.density.anim <- crime.density +
transition_states(crime$year,
transition_length = 10,
state_length = 50) +
labs(title = "Year: {closest_state}")
animate(crime.density.anim, nframes = 50)
Female Crime Reports, By Relative Density |
Male Crime Reports, By Relative Density |
The software I was using on macOS, RMarkdown, does not always recognize path variables when specified in bash_profile. To stitch the images I produced together into gif’s, I had to use ImageMagick from my computer’s Terminal application. Otherwise, everything else was done with this R code.
#### LIBRARIES ####
## DATA MANAGEMENT
library(tidyverse)
library(magrittr)
library(tictoc)
library(MASS)
## MAPS
library(sf)
library(rgdal)
# devtools::install_github("dkahle/ggmap", ref = "tidyup", force=TRUE)
library("ggmap")
library(sp)
library(scales)
#Set your API Key
ggmap::register_google(key = "AIzaSyBgYVpL1in38KcEnznCFwmRKz2d1VJKSe4")
# library(ggiraph)
# library(widgetframe)
## VISUALIZATION
# devtools::install_github('cran/ggplot2')
library(ggplot2)
library(gganimate)
library(gifski)
## install.packages("/Users/charliecarter/Downloads/gifski_0.8.6.tar", repos = NULL,type = "binary")
## get contour lines that define
## point density circles
density.poly <- contourLines(
kde2d(crime$lon, crime$lat,
lims = c(
expand_range(range(crime$lon), add = 0.5),
expand_range(range(crime$lat), add = 0.5)
))
)
## create column that loop will modify
crime$density <- 0
## from highest to lowest density levels (which is default)
## get polygons and get points inside them, assign density val
for (i in 1:length(density.poly)) {
hold.data <- point.in.polygon(crime$lon, crime$lat,
density.poly[[i]]$x, density.poly[[i]]$y)
crime$density[which(hold.data==1)] <- density.poly[[i]]$level
}
## trying alternative density measure
## https://slowkow.com/notes/ggplot2-color-by-density/
# Get density of points in 2 dimensions.
# @param x A numeric vector.
# @param y A numeric vector.
# @param n Create a square n by n grid to compute density.
# @return The density within each square.
get_density <- function(x, y, ...) {
dens <- MASS::kde2d(x, y, ...)
ix <- findInterval(x, dens$x)
iy <- findInterval(y, dens$y)
ii <- cbind(ix, iy)
return(dens$z[ii])
}
fem.crime <- crime %>%
filter(Victim.Sex == "F")
male.crime <- crime %>%
filter(Victim.Sex == "M")
crime$dens_f <- get_density(crime$lon, crime$lat, n= 400)
fem.crime$dens_f <- get_density(fem.crime$lon, fem.crime$lat, n= 300)
male.crime$dens_f <- get_density(male.crime$lon, male.crime$lat, n= 300)
## Create column with year data
crime <- crime %>%
mutate(Date.Occurred = as.Date(Date.Occurred, format = "%m/%d/%Y")) %>%
mutate(year = format(Date.Occurred, "%Y")) %>%
mutate(year = as.factor(year))
###########
# ggmap::register_google(key = "AIzaSyBgYVpL1in38KcEnznCFwmRKz2d1VJKSe4")
# ggmap_show_api_key()
# la.map <- ggmap(get_googlemap("Los Angeles, California"))
setwd("/Users/charliecarter/Documents/CalMatters/Data")
saveRDS(la.map, file = "LA_map")
### FEMALE ####
if(!dir.exists("/Users/charliecarter/examples")) {
dir.create("/Users/charliecarter/examples")
}
if(!dir.exists("/Users/charliecarter/examples/fem_crime")) {
dir.create("/Users/charliecarter/examples/fem_crime")
}
setwd("/Users/charliecarter/examples/fem_crime")
# iterate over years and make map png's
png(file="femcrime%02d.png", width=400, height=400)
for (year in levels(fem.crime$year)){
print(year)
#### point with color test ####
crime.density <- la.map +
geom_point(fem.crime[fem.crime$year == year,1:ncol(fem.crime)],
mapping = aes(x = lon,
y = lat,
alpha = 0.01,
color = dens_f),
size = 0.005,
shape = ".") +
scale_color_viridis_c(option = "A", alpha = 0.5) +
labs(title = paste("Los Angeles Crime Reports With Female Victims,\nBy Density\nYear: ",
year)) +
theme(
legend.position='none'
)
plot(crime.density)
}
dev.off()
### MALE ####
if(!dir.exists("/Users/charliecarter/examples")) {
dir.create("/Users/charliecarter/examples")
}
if(!dir.exists("/Users/charliecarter/examples/male_crime")) {
dir.create("/Users/charliecarter/examples/male_crime")
}
setwd("/Users/charliecarter/examples/male_crime")
# iterate over years and make map png's
png(file="malecrime%02d.png", width=400, height=400)
for (year in levels(male.crime$year)) {
print(year)
#### point with color test ####
crime.density <- la.map +
geom_point(male.crime[male.crime$year == year, 1:ncol(male.crime)],
mapping = aes(x = lon,
y = lat,
alpha = 0.01,
color = dens_f),
size = 0.005,
shape = ".") +
scale_color_viridis_c(option = "A", alpha = 0.5) +
labs(title = paste("Los Angeles Crime Reports With Male Victims,\nBy Density\nYear: ",
year)) +
theme(
legend.position='none'
)
plot(crime.density)
}
dev.off()